#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
#TODO: documentation!
"""


__version__ = '$Id: engine.py 200 2008-03-04 21:01:54Z DLacewell $'

#import logging

import pyglet
from pyglet import clock
from pyglet import gl

from bipy import viewmanager


class EngineClass(pyglet.window.Window):
    def __init__(self, *args, **named):
        super(EngineClass, self).__init__(*args, **named)
        # Event attributes
        self.register_event_type('on_update')
        self.register_event_type('on_draw')
        self.register_event_type('on_scene_freeze')
        self.register_event_type('on_scene_unfreeze')
        self.register_event_type('on_scene_enter')
        self.register_event_type('on_scene_leave')
        # scene attributes
        self.__scenes = []
        self.__current_scene = None
        # Clock attributes
        self.fps_display = pyglet.clock.ClockDisplay()
        # Viewmanager
        self.view_manager = viewmanager.ViewManager()
        # FPS Display
        self.display_fps = True
        # Debug attributes
        self._debug_font = pyglet.font.load('Terminal', 14)
        
    def get_current_scene(self):
        return self.__current_scene
    
    def push_scene(self, scene):
        # If there is a running scene
        if self.__current_scene:
            # Freeze the scene onto the stack
            self.__scenes.append(self.__current_scene)
            self.dispatch_event('on_scene_freeze')
            self.pop_handlers()
        # Set the new active scene
        self.__current_scene = scene
        self.push_handlers(self.__current_scene)
        self.dispatch_event('on_scene_enter')
        
    def pop_scene(self):
        # If there is a running scene
        if self.__current_scene:
            # Leave event
            self.dispatch_event('on_scene_leave')
            self.pop_handlers()
            # Clean scene's views
            self.view_manager.pop_views()
            try:
                # Unfreeze the last scene
                self.__current_scene = self.__scenes.pop()
                self.push_handlers( self.__current_scene )
                self.dispatch_event('on_scene_unfreeze')
            except IndexError:
                self.__current_scene = None
                
    def get_num_scenes(self):
        # Frozen scenes and the running scene
        return len(self.__scenes) + (1 if self.__current_scene else 0)

    def clear_scenes(self):
        # Pop each scene
        for i in range(self.get_num_scenes()):
            self.pop_scene()
        self.__current_scene = None

    def run(self, scene):
        # Push initialized scene object
        self.push_scene( scene )
        # Pre-tick
        clock.tick()
        # Show window
        self.set_visible()
        # Run while there is a scene on the stack
        while self.__current_scene:
            # Get deltatime and update
            dt = clock.tick()
            self.dispatch_event('on_update', dt)
            self.dispatch_event('on_draw')
            # Dispatch events
            self.dispatch_events()
            
        self.has_exit = True
        
    def on_close(self):
        self.clear_scenes()
